home *** CD-ROM | disk | FTP | other *** search
- ;=========================================================================
- ; XSCALE1.ASM by John A. Slagel, jas37876@uxa.cso.uiuc.edu
- ; This is some code to do bitmap scaling in VGA Mode X. It can scale a
- ; bitmap of any size down to 2 pixels wide, or up to thousands of pixels
- ; wide. It performs complete clipping, with only a small constant amount
- ; of time to clip, no matter how huge the image is. It draws column by
- ; column to reduce the number of plane switches, which are slow. The inner
- ; column loop has been optimized for no memory accesses, except to read or
- ; write a pixel. This uses MASM 5.1 features, and can be compiled in any
- ; memory model by changing the .MODEL line, but make sure that you always
- ; pass a far pointer to the bitmap data, regardless of memory model.
- ; C-callable as:
- ; void XSCALE1( int X, int Y, int DW, int DY,
- ; int SW, int SH, void far * Bitmap );
- ; X,Y are the upper left-hand coordinates of where to draw the bitmap.
- ; DW,DH are the width and height of the SCALEed bitmap
- ; SW,SH are the width and height of the source bitmap.
- ; Bitmap is a pointer to the bitmap bits.
- ;
- ; Routine has been modified for 32 bit protected mode by John McCarthy.
- ; John McCarthy thanks John A. Slagel for providing this code, and hopes
- ; John A. Slagel is not offended by the changes.
- ;
- ;==========================================================================
-
- public draw_scale
- public tdraw_scale
- public tdraw_scale4
- public xscale1
- public xscale2
- public xscale4
- public repeat_bitmap
-
- ; uses edi esi, destx:word, desty:word,
- ; destwidth:word, destheight:word,
- ; sourcewidth:word, sourceheight:word,
- ; bitmap:far ptr
-
- draw_scale:
- mov bitmap,esi
- mov destwidth,ax
- mov destheight,bx
- mov destx,cx
- mov desty,dx
-
- xscale1:
- cmp destwidth, 2 ; if destination width is less than 2
- jl done ; then don't draw it.
-
- cmp destheight, 2 ; if destination height is less than 2
- jl done ; then don't draw it.
-
- mov ax, desty ; if it is completely below the
- cmp ax, clipbt ; lower clip bondry,
- jg done ; then don't draw it.
-
- add ax, destheight ; if it is above clip boundries
- dec ax ; then don't draw it.
- cmp ax, cliptp
- jl done
-
- mov ax, destx ; if it is to the right of the
- mov cx, cliprt ; right clip boundry
- cmp ax, cliprt ; then don't draw it.
- jg done
-
- add ax, destwidth ; if it is completely to the left
- dec ax ; of the left clip boundry,
- cmp ax, cliplt ; then don't draw it.
- jl done
-
- mov esi, bitmap ; make esi point to bitmap data
- lodsw ; get source x width
- mov sourcewidth,ax
- lodsw ; get source y height
- mov sourceheight,ax
-
- mov ax, destwidth ; clippedwidth is initially set to
- mov clippedwidth, ax ; the requested dest width.
-
- shl ax,1 ; initialize the x decision var
- neg ax ; to be -2*destwidth
- mov decisionx, ax ;
-
- mov ax, destheight ; clippedheight is initially set to
- mov clippedheight, ax ; the requested dest size.
-
- shl ax,1 ; initialize the y decision var
- neg ax ; to be -2*destheight
- mov decisiony, ax ;
-
- movsx eax, cliptp ; if y is below the top
- mov edx, eax ; clipping boundry, then we don't
- sub dx, desty ; need to clip the top, so we can
- js s notopclip ; jump over the clipping stuff.
-
- mov desty, ax ; this block performs clipping on the
- sub clippedheight, dx ; top of the bitmap. i have heavily
- movsx ecx, sourceheight ; optimized this block to use only 4
- imul ecx, edx ; 32-bit registers, so i'm not even
- mov eax, ecx ; gonna try to explain what it's doing.
- cdq ; but i can tell you what results from
- movsx ebx, destheight ; this: the decisiony var is updated
- idiv ebx ; to start at the right clipped row.
- movsx edx, sourcewidth ; y is moved to the top clip
- imul edx, eax ; boundry. clippedheight is lowered since
- add esi, edx ; we won't be drawing all the requested
- imul eax, ebx ; rows. esi is changed to point over
- sub ecx, eax ; the bitmap data that is clipped off.
- sub ecx, ebx ;
- shl ecx, 1 ;
- mov decisiony, cx ; <end of top clipping block >
-
- notopclip:
- mov ax, desty ; if the bitmap doesn't extend over the
- add ax, clippedheight ; bottom clipping boundry, then we
- dec ax ; don't need to clip the bottom, so we
- cmp ax, clipbt ; can jump over the bottom clip code.
- jle s nobottomclip ;
-
- mov ax, clipbt ; clip off the bottom by reducing the
- sub ax, desty ; clippedheight so that the bitmap won't
- inc ax ; extend over the lower clipping
- mov clippedheight, ax ; boundry.
-
- nobottomclip:
- movsx eax, cliplt ; if x is to the left of the
- mov edx, eax ; top clipping boundry, then we don't
- sub dx, destx ; need to clip the left, so we can
- js s noleftclip ; jump over the clipping stuff.
-
- mov destx, ax ; this block performs clipping on the
- sub clippedwidth, dx ; left of the bitmap. i have heavily
- movsx ecx, sourcewidth ; optimized this block to use only 4
- imul ecx, edx ; 32-bit registers, so i'm not even
- mov eax, ecx ; gonna try to explain what it's doing.
- cdq ; but i can tell you what results from
- movsx ebx, destwidth ; this: the decisionx var is updated
- idiv ebx ; to start at the right clipped column.
- add esi, eax ; x is moved to the left clip
- imul eax, ebx ; boundry. clippedwidth is reduced since
- sub ecx, eax ; we won't be drawing all the requested
- sub ecx, ebx ; cols. esi is changed to point over
- shl ecx, 1 ; the bitmap data that is clipped off.
- mov decisionx, cx ; <end of left clipping block >
-
- noleftclip:
- mov ax, destx ; if the bitmap doesn't extend over the
- add ax, clippedwidth ; right clipping boundry, then we
- dec ax ; don't need to clip the right, so we
- cmp ax, cliprt ; can jump over the right clip code.
- jle s noclipright ;
-
- mov ax, cliprt ; clip off the right by reducing the
- sub ax, destx ; clippedwidth so that the bitmap won't
- inc ax ; extend over the right clipping
- mov clippedwidth, ax ; boundry.
-
- ;calculate starting video address
- noclipright:
- movzx edi, desty ; we are going to set edi to start point
- imul edi, xactual/4
- movzx eax, destx ; the offset edi is
- mov cx, ax ; calculated by:
- shr ax, 2 ; di = y*80+x/2
- add eax, current_page
- add edi,eax ; edi is ready!
-
- mov dx, sc_index+1 ; point the vga sequencer to the map
- ; mov al, map_mask ; mask register, so that we only need
- ; out dx, al ; to send out 1 byte per column.
-
- ; inc dx ; move to the sequencer's data register.
- and cx, 3 ; calculate the starting plane. this is
- mov al, 11h ; just:
- shl al, cl ; plane = (11h << (x and 3))
- out dx, al ; select the first plane.
-
- movzx ecx, sourcewidth ; use cx for source width
- mov xad, ecx
- shl sourcewidth,1
-
- align 16 ; since this point gets jumped to a lot,
- ; make sure that it is dword aligned.
- rowloop:
- push esi ; save the starting source index
- push edi ; save the starting dest index
- push ax ; save the current plane mask
- push bp ; save the current base pointer
-
- mov cx, clippedheight ; use al for row counter (0-239)
- mov bx, decisiony ; use bx for decision variable
- mov dx, sourceheight ; use dx for source height * 2
- shl dx, 1
- mov bp, destheight ; use bp for dest height * 2
- shl bp, 1
- mov ah, [esi] ; get the first source pixel
-
- align 4 ; common jump point... align for speed.
- columnloop:
- mov [edi], ah ; draw a pixel
- dec cx ; decrement line counter
- jz s donewithcol ; see if we're done with this column
- add edi, xactual/4 ; go on to the next screen row
- add bx, dx ; increment the decision variable
- js s columnloop ; draw this source pixel again
-
- incsourcerow:
- add esi, xad ; move to the next source pixel
- sub bx, bp ; decrement the decision variable
- jns s incsourcerow ; see if we need to skip another source pixel
- mov ah, [esi] ; get the next source pixel
- jmp s columnloop ; start drawing this pixel
-
- donewithcol:
- pop bp ; restore bp to access variables
- pop ax ; restore al = plane mask
- pop edi ; restore di to top row of screen
- pop esi ; restore si to top row of source bits
-
- rol al, 1 ; move to next plane
- adc edi, 0 ; go on to next screen column
- mov dx, sc_data ; tell the vga what column we're in
- out dx, al ; by updating the map mask register
-
- mov bx, decisionx ; use bx for the x decision variable
- add bx, sourcewidth ; increment the x decision variable
- js s nextcol ; jump if we're still in the same source col.
- mov dx, destwidth ; dx = w * 2
- shl dx, 1
- incsourcecol:
- inc esi ; move to next source column
- sub bx, dx ; decrement x decision variable
- jns s incsourcecol ; see if we skip another source column
- nextcol:
- mov decisionx, bx ; free up bx for colloop
- dec clippedwidth ; if we're not at last column
- jnz rowloop ; then do another column
- done:
- ret ; we're done!
-
- ; draw transparent bitmap. any bytes that = 0 are skipped
-
- tdraw_scale:
- mov bitmap,esi
- mov destwidth,ax
- mov destheight,bx
- mov destx,cx
- mov desty,dx
-
- xscale2:
- cmp destwidth, 2 ; if destination width is less than 2
- jl s done ; then don't draw it.
-
- cmp destheight, 2 ; if destination height is less than 2
- jl s done ; then don't draw it.
-
- mov ax, desty ; if it is completely below the
- cmp ax, clipbt ; lower clip bondry,
- jg s done ; then don't draw it.
-
- add ax, destheight ; if it is above clip boundries
- dec ax ; then don't draw it.
- cmp ax, cliptp
- jl s done
-
- mov ax, destx ; if it is to the right of the
- mov cx, cliprt ; right clip boundry
- cmp ax, cliprt ; then don't draw it.
- jg s done
-
- add ax, destwidth ; if it is completely to the left
- dec ax ; of the left clip boundry,
- cmp ax, cliplt ; then don't draw it.
- jl s done
-
- mov esi, bitmap ; make esi point to bitmap data
- lodsw ; get source x width
- mov sourcewidth,ax
- lodsw ; get source y height
- mov sourceheight,ax
-
- mov ax, destwidth ; clippedwidth is initially set to
- mov clippedwidth, ax ; the requested dest width.
-
- shl ax,1 ; initialize the x decision var
- neg ax ; to be -2*destwidth
- mov decisionx, ax ;
-
- mov ax, destheight ; clippedheight is initially set to
- mov clippedheight, ax ; the requested dest size.
-
- shl ax,1 ; initialize the y decision var
- neg ax ; to be -2*destheight
- mov decisiony, ax ;
-
- movsx eax, cliptp ; if y is below the top
- mov edx, eax ; clipping boundry, then we don't
- sub dx, desty ; need to clip the top, so we can
- js s notopclip2 ; jump over the clipping stuff.
-
- mov desty, ax ; this block performs clipping on the
- sub clippedheight, dx ; top of the bitmap. i have heavily
- movsx ecx, sourceheight ; optimized this block to use only 4
- imul ecx, edx ; 32-bit registers, so i'm not even
- mov eax, ecx ; gonna try to explain what it's doing.
- cdq ; but i can tell you what results from
- movsx ebx, destheight ; this: the decisiony var is updated
- idiv ebx ; to start at the right clipped row.
- movsx edx, sourcewidth ; y is moved to the top clip
- imul edx, eax ; boundry. clippedheight is lowered since
- add esi, edx ; we won't be drawing all the requested
- imul eax, ebx ; rows. esi is changed to point over
- sub ecx, eax ; the bitmap data that is clipped off.
- sub ecx, ebx ;
- shl ecx, 1 ;
- mov decisiony, cx ; <end of top clipping block >
-
- notopclip2:
- mov ax, desty ; if the bitmap doesn't extend over the
- add ax, clippedheight ; bottom clipping boundry, then we
- dec ax ; don't need to clip the bottom, so we
- cmp ax, clipbt ; can jump over the bottom clip code.
- jle s nobottomclip2
-
- mov ax, clipbt ; clip off the bottom by reducing the
- sub ax, desty ; clippedheight so that the bitmap won't
- inc ax ; extend over the lower clipping
- mov clippedheight, ax ; boundry.
-
- nobottomclip2:
- movsx eax, cliplt ; if x is to the left of the
- mov edx, eax ; top clipping boundry, then we don't
- sub dx, destx ; need to clip the left, so we can
- js s noleftclip2 ; jump over the clipping stuff.
-
- mov destx, ax ; this block performs clipping on the
- sub clippedwidth, dx ; left of the bitmap. i have heavily
- movsx ecx, sourcewidth ; optimized this block to use only 4
- imul ecx, edx ; 32-bit registers, so i'm not even
- mov eax, ecx ; gonna try to explain what it's doing.
- cdq ; but i can tell you what results from
- movsx ebx, destwidth ; this: the decisionx var is updated
- idiv ebx ; to start at the right clipped column.
- add esi, eax ; x is moved to the left clip
- imul eax, ebx ; boundry. clippedwidth is reduced since
- sub ecx, eax ; we won't be drawing all the requested
- sub ecx, ebx ; cols. esi is changed to point over
- shl ecx, 1 ; the bitmap data that is clipped off.
- mov decisionx, cx ; <end of left clipping block >
-
- noleftclip2:
- mov ax, destx ; if the bitmap doesn't extend over the
- add ax, clippedwidth ; right clipping boundry, then we
- dec ax ; don't need to clip the right, so we
- cmp ax, cliprt ; can jump over the right clip code.
- jle s noclipright2
-
- mov ax, cliprt ; clip off the right by reducing the
- sub ax, destx ; clippedwidth so that the bitmap won't
- inc ax ; extend over the right clipping
- mov clippedwidth, ax ; boundry.
-
- ;calculate starting video address
- noclipright2:
- movsx edi, desty ; we are going to set edi to start point
- imul edi, xactual/4
- movsx eax, destx ; the offset edi is
- mov cx, ax ; calculated by:
- shr eax, 2 ; edi = y*80+x/2
- add eax, current_page
- add edi,eax ; edi is ready!
-
- mov dx, sc_index+1 ; point the vga sequencer to the map
- ; mov al, map_mask ; mask register, so that we only need
- ; out dx, al ; to send out 1 byte per column.
-
- ; inc dx ; move to the sequencer's data register.
- and cx, 3 ; calculate the starting plane. this is
- mov al, 11h ; just:
- shl al, cl ; plane = (11h << (x and 3))
- out dx, al ; select the first plane.
-
- movzx ecx, sourcewidth ; use cx for source width
- mov xad, ecx
- shl sourcewidth,1
-
- align 16 ; since this point gets jumped to a lot,
- ; make sure that it is dword aligned.
- rowloop2:
- push esi ; save the starting source index
- push edi ; save the starting dest index
- push ax ; save the current plane mask
- push bp ; save the current base pointer
-
- mov cx, clippedheight ; use al for row counter (0-239)
- mov bx, decisiony ; use bx for decision variable
- mov dx, sourceheight ; use dx for source height * 2
- shl dx, 1
- mov bp, destheight ; use bp for dest height * 2
- shl bp, 1
- mov ah, [esi] ; get the first source pixel
- or ah,ah
- jz s null_loop ; if zero, perform null loop
-
- align 4 ; common jump point... align for speed.
- columnloop2:
- mov [edi], ah ; draw a pixel
- dec cx ; decrement line counter
- jz s donewithcol2 ; see if we're done with this column
- add edi, xactual/4 ; go on to the next screen row
- add bx, dx ; increment the decision variable
- js s columnloop2 ; draw this source pixel again
-
- incsourcerow2:
- add esi, xad ; move to the next source pixel
- sub bx, bp ; decrement the decision variable
- jns s incsourcerow2 ; see if we need to skip another source pixel
- mov ah, [esi] ; get the next source pixel
- cmp ah,0
- jz s null_loop
- jmp s columnloop2 ; start drawing this pixel
-
- donewithcol2:
- pop bp ; restore bp to access variables
- pop ax ; restore al = plane mask
- pop edi ; restore di to top row of screen
- pop esi ; restore si to top row of source bits
-
- rol al, 1 ; move to next plane
- adc edi, 0 ; go on to next screen column
- mov dx, sc_data ; tell the vga what column we're in
- out dx, al ; by updating the map mask register
-
- mov bx, decisionx ; use bx for the x decision variable
- add bx, sourcewidth ; increment the x decision variable
- js s nextcol2 ; jump if we're still in the same source col.
- mov dx, destwidth ; dx = w * 2
- shl dx, 1
- incsourcecol2:
- inc esi ; move to next source column
- sub bx, dx ; decrement x decision variable
- jns s incsourcecol2 ; see if we skip another source column
- nextcol2:
- mov decisionx, bx ; free up bx for colloop
- dec clippedwidth ; if we're not at last column
- jnz rowloop2 ; then do another column
- done2:
- ret ; we're done!
-
- align 16 ; common jump point... align for speed.
- null_loop:
- dec cx ; decrement line counter
- jz s donewithcol2 ; see if we're done with this column
- add edi, xactual/4 ; go on to the next screen row
- add bx, dx ; increment the decision variable
- js s null_loop ; perform more increments
- jmp s incsourcerow2
-
- ; draw repeated bit map. good for backgrounds in menus and title screens.
- ; routine is NOT intended for animation because it is slow. uses scale routine
- ; because scale routine clips bitmaps. sloppy routine just draws all over the
- ; place and lets the scale clip borders handle the rest.
- ;
- ; repeat_bitmap (seg bitmap, x1%, y1%, x2%, y2%)
- ;
- ; remember: first two words of bitmap define width and height
-
- rb_stack struc
- rb_wide dw ? ; height and width of bitmap
- rb_height dw ?
- rb_curx dw ? ; current bitmap location
- rb_cury dw ?
- rb_oldy2 dw ? ; old cliping borders save
- rb_oldx2 dw ?
- rb_oldy1 dw ?
- rb_oldx1 dw ?
- dd ?x3 ; edi, esi, ebp
- dd ? ; caller
- rb_y2 dw ? ; y2
- rb_x2 dw ? ; x2
- rb_y1 dw ? ; y1
- rb_x1 dw ? ; x1
- rb_bitmap dd ? ; offset to bitmap
- rb_stack ends
-
- repeat_bitmap:
- push ebp esi edi ; preserve important registers
- sub esp, 16 ; allocate workspace
- mov ebp, esp ; set up stack frame
-
- mov ax,cliplt ; save old borders just in case
- mov [ebp].rb_oldx1,ax
- mov ax,cliprt
- mov [ebp].rb_oldx2,ax
- mov ax,cliptp
- mov [ebp].rb_oldy1,ax
- mov ax,clipbt
- mov [ebp].rb_oldy2,ax
-
- mov x1,4
-
- mov ax,[ebp].rb_x1 ; set new borders for clipping
- mov cliplt,ax
- mov ax,[ebp].rb_x2
- mov cliprt,ax
- mov ax,[ebp].rb_y1
- mov cliptp,ax
- mov ax,[ebp].rb_y2
- mov clipbt,ax
-
- mov [ebp].rb_curx,0 ; we could start at x1,y1 but this
- mov [ebp].rb_cury,0 ; will make offset backgrounds
-
- mov esi,[ebp].rb_bitmap
- mov bitmap,esi
- lodsw ; set destination width same as original
- mov [ebp].rb_wide,ax
- lodsw
- mov [ebp].rb_height,ax
- nextline:
- mov ax,[ebp].rb_wide
- mov destwidth,ax
- mov ax,[ebp].rb_height
- mov destheight,ax
-
- mov ax,[ebp].rb_curx
- mov destx,ax
- mov ax,[ebp].rb_cury
- mov desty,ax
-
- push ebp
- call xscale2 ; draw a transparent bitmap
- pop ebp
-
- mov ax,[ebp].rb_curx
- add ax,[ebp].rb_wide
- mov [ebp].rb_curx,ax
- cmp ax,[ebp].rb_x2
- jle s nextline
-
- mov [ebp].rb_curx,0
-
- mov ax,[ebp].rb_cury
- add ax,[ebp].rb_height
- mov [ebp].rb_cury,ax
- cmp ax,[ebp].rb_y2
- jle s nextline
-
- mov ax,[ebp].rb_oldx1
- mov cliplt,ax
- mov ax,[ebp].rb_oldx2
- mov cliprt,ax
- mov ax,[ebp].rb_oldy1
- mov cliptp,ax
- mov ax,[ebp].rb_oldy2
- mov clipbt,ax
-
- add esp, 16
- pop edi esi ebp
- ret 12
-
- ; draw transparent bitmap using 1/4 xmode method. - draws every 4 pixels alike.
- ; great for explosions/smoke where the bitmap does not have to be very
- ; accuratly drawn - much faster
-
- done4: ret
-
- tdraw_scale4:
- mov bitmap,esi
- mov destwidth,ax
- mov destheight,bx
- mov destx,cx
- mov desty,dx
-
- xscale4:
- cmp destwidth, 2 ; if destination width is less than 2
- jl s done4 ; then don't draw it.
-
- cmp destheight, 2 ; if destination height is less than 2
- jl s done4 ; then don't draw it.
-
- mov ax, desty ; if it is completely below the
- cmp ax, clipbt ; lower clip bondry,
- jg s done4 ; then don't draw it.
-
- add ax, destheight ; if it is above clip boundries
- dec ax ; then don't draw it.
- cmp ax, cliptp
- jl s done4
-
- mov ax, destx ; if it is to the right of the
- mov cx, cliprt ; right clip boundry
- cmp ax, cliprt ; then don't draw it.
- jg s done4
-
- add ax, destwidth ; if it is completely to the left
- dec ax ; of the left clip boundry,
- cmp ax, cliplt ; then don't draw it.
- jl s done4
-
- mov esi, bitmap ; make esi point to bitmap data
- lodsw ; get source x width
- mov sourcewidth,ax
- lodsw ; get source y height
- mov sourceheight,ax
-
- mov ax, destwidth ; clippedwidth is initially set to
- mov clippedwidth, ax ; the requested dest width.
-
- shl ax,1 ; initialize the x decision var
- neg ax ; to be -2*destwidth
- mov decisionx, ax ;
-
- mov ax, destheight ; clippedheight is initially set to
- mov clippedheight, ax ; the requested dest size.
-
- shl ax,1 ; initialize the y decision var
- neg ax ; to be -2*destheight
- mov decisiony, ax ;
-
- movsx eax, cliptp ; if y is below the top
- mov edx, eax ; clipping boundry, then we don't
- sub dx, desty ; need to clip the top, so we can
- js s notopclip4 ; jump over the clipping stuff.
-
- mov desty, ax ; this block performs clipping on the
- sub clippedheight, dx ; top of the bitmap. i have heavily
- movsx ecx, sourceheight ; optimized this block to use only 4
- imul ecx, edx ; 32-bit registers, so i'm not even
- mov eax, ecx ; gonna try to explain what it's doing.
- cdq ; but i can tell you what results from
- movsx ebx, destheight ; this: the decisiony var is updated
- idiv ebx ; to start at the right clipped row.
- movsx edx, sourcewidth ; y is moved to the top clip
- imul edx, eax ; boundry. clippedheight is lowered since
- add esi, edx ; we won't be drawing all the requested
- imul eax, ebx ; rows. esi is changed to point over
- sub ecx, eax ; the bitmap data that is clipped off.
- sub ecx, ebx ;
- shl ecx, 1 ;
- mov decisiony, cx ; <end of top clipping block >
-
- notopclip4:
- mov ax, desty ; if the bitmap doesn't extend over the
- add ax, clippedheight ; bottom clipping boundry, then we
- dec ax ; don't need to clip the bottom, so we
- cmp ax, clipbt ; can jump over the bottom clip code.
- jle s nobottomclip4
-
- mov ax, clipbt ; clip off the bottom by reducing the
- sub ax, desty ; clippedheight so that the bitmap won't
- inc ax ; extend over the lower clipping
- mov clippedheight, ax ; boundry.
-
- nobottomclip4:
- movsx eax, cliplt ; if x is to the left of the
- mov edx, eax ; top clipping boundry, then we don't
- sub dx, destx ; need to clip the left, so we can
- js s noleftclip4 ; jump over the clipping stuff.
-
- mov destx, ax ; this block performs clipping on the
- sub clippedwidth, dx ; left of the bitmap. i have heavily
- movsx ecx, sourcewidth ; optimized this block to use only 4
- imul ecx, edx ; 32-bit registers, so i'm not even
- mov eax, ecx ; gonna try to explain what it's doing.
- cdq ; but i can tell you what results from
- movsx ebx, destwidth ; this: the decisionx var is updated
- idiv ebx ; to start at the right clipped column.
- add esi, eax ; x is moved to the left clip
- imul eax, ebx ; boundry. clippedwidth is reduced since
- sub ecx, eax ; we won't be drawing all the requested
- sub ecx, ebx ; cols. esi is changed to point over
- shl ecx, 1 ; the bitmap data that is clipped off.
- mov decisionx, cx ; <end of left clipping block >
-
- noleftclip4:
- mov ax, destx ; if the bitmap doesn't extend over the
- add ax, clippedwidth ; right clipping boundry, then we
- dec ax ; don't need to clip the right, so we
- cmp ax, cliprt ; can jump over the right clip code.
- jle s noclipright4
-
- mov ax, cliprt ; clip off the right by reducing the
- sub ax, destx ; clippedwidth so that the bitmap won't
- inc ax ; extend over the right clipping
- mov clippedwidth, ax ; boundry.
-
- ;calculate starting video address
- noclipright4:
- movsx edi, desty ; we are going to set edi to start point
- imul edi, xactual/4
- movsx eax, destx ; the offset edi is
- mov cx, ax ; calculated by:
- shr eax, 2 ; edi = y*80+x/2
- add eax, current_page
- add edi,eax ; edi is ready!
-
- mov dx, sc_index+1 ; point the vga sequencer to the map
- ; mov al, map_mask ; mask register, so that we only need
- ; out dx, al ; to send out 1 byte per column.
-
- ; inc dx ; move to the sequencer's data register.
- mov al, all_planes
- out dx, al ; select the first plane.
-
- movzx ecx, sourcewidth ; use cx for source width
- mov xad, ecx
-
- shl sourcewidth,1+2 ; 4 times as fast
- shr clippedwidth,2 ; 1/4 of the plots
-
- cmp clippedwidth,0 ; check if <4 wide
- jne s rowloop4
- inc clippedwidth
-
- align 16 ; since this point gets jumped to a lot,
- ; make sure that it is dword aligned.
- rowloop4:
- push esi ; save the starting source index
- push edi ; save the starting dest index
- push bp ; save the current base pointer
-
- mov cx, clippedheight ; use al for row counter (0-239)
- mov bx, decisiony ; use bx for decision variable
- mov dx, sourceheight ; use dx for source height * 2
- shl dx, 1
- mov bp, destheight ; use bp for dest height * 2
- shl bp, 1
- mov ah, [esi] ; get the first source pixel
- or ah,ah
- jz s null_loop4 ; if zero, perform null loop
-
- align 4 ; common jump point... align for speed.
- columnloop4:
- mov [edi], ah ; draw a pixel
- dec cx ; decrement line counter
- jz s donewithcol4 ; see if we're done with this column
- add edi, xactual/4 ; go on to the next screen row
- add bx, dx ; increment the decision variable
- js s columnloop4 ; draw this source pixel again
-
- incsourcerow4:
- add esi, xad ; move to the next source pixel
- sub bx, bp ; decrement the decision variable
- jns s incsourcerow4 ; see if we need to skip another source pixel
- mov ah, [esi] ; get the next source pixel
- or ah,ah
- jz s null_loop4
- jmp s columnloop4 ; start drawing this pixel
-
- donewithcol4:
- pop bp ; restore bp to access variables
- pop edi ; restore di to top row of screen
- pop esi ; restore si to top row of source bits
-
- add edi, 1 ; go on to next screen column
-
- mov bx, decisionx ; use bx for the x decision variable
- add bx, sourcewidth ; increment the x decision variable
- mov dx, destwidth ; dx = w * 2
- shl dx, 1
- incsourcecol4:
- inc esi ; move to next source column
- sub bx, dx ; decrement x decision variable
- jns s incsourcecol4 ; see if we skip another source column
- nextcol4:
- mov decisionx, bx ; free up bx for colloop
- dec clippedwidth ; if we're not at last column
- jnz rowloop4 ; then do another column
-
- ret ; we're done!
-
- align 16 ; common jump point... align for speed.
- null_loop4:
- dec cx ; decrement line counter
- jz s donewithcol4 ; see if we're done with this column
- add edi, xactual/4 ; go on to the next screen row
- add bx, dx ; increment the decision variable
- js s null_loop4 ; perform more increments
- jmp s incsourcerow4
-